package com.baturu.mybatisminus.util;

import com.baturu.mybatisminus.MinusConfiguration;
import com.baturu.mybatisminus.annotation.info.ColumnAnnotation;
import com.baturu.mybatisminus.model.FieldInfo;
import org.apache.ibatis.type.*;

import java.lang.reflect.Field;

/**
 * FieldParseUtils
 *
 * @author huangbin
 **/
public class FieldParseUtils {

    public static FieldInfo parseField(Field field, MinusConfiguration config) {
        FieldInfo fieldInfo = new FieldInfo();
        fieldInfo.setPropertyType(field.getType());
        fieldInfo.setProperty(field.getName());
        fieldInfo.setEscapedProperty(SqlReservedWords.escapeIfNecessary(field.getName()));

        ColumnAnnotation column = AnnotationUtils.parseColumnAnnotation(field);
        String columnName = field.getName();
        if (column == null && config.getColumnNameUnderLine()) {
            columnName = StringUtils.camelToUnderline(field.getName());
            fieldInfo.setPropertyColumnEqual(false);
        } else if (column != null && StringUtils.isNotEmpty(column.value())) {
            columnName = column.value();
            if (!columnName.equals(field.getName())) {
                fieldInfo.setPropertyColumnEqual(false);
            }
        }
        fieldInfo.setColumn(columnName);
        fieldInfo.setEscapedColumn(SqlReservedWords.escapeIfNecessary(columnName));

        if (column == null) {
            return fieldInfo;
        }
        fieldInfo.setInsertable(column.insertable());
        fieldInfo.setUpdatable(column.updatable());
        fieldInfo.setIgnoreEmptyString(column.emptyStringAsNull());
        registerTypeHandler(column, fieldInfo, config);
        return fieldInfo;
    }


    private static void registerTypeHandler(ColumnAnnotation column, FieldInfo fieldInfo, MinusConfiguration config) {
        if (column.typeHandler() == UnknownTypeHandler.class) {
            return;
        }
        Class<? extends TypeHandler> typeHandler = column.typeHandler();
        MappedTypes mappedTypes = typeHandler.getAnnotation(MappedTypes.class);
        MappedJdbcTypes mappedJdbcTypes = typeHandler.getAnnotation(MappedJdbcTypes.class);
        if (mappedJdbcTypes == null || mappedTypes == null) {
            return;
        }
        fieldInfo.setTypeHandler(typeHandler);
        for (Class<?> mappedType : mappedTypes.value()) {
            for (JdbcType jdbcType : mappedJdbcTypes.value()) {
                config.getTypeHandlerRegistry().register(mappedType, jdbcType, typeHandler);
                if (mappedJdbcTypes.includeNullJdbcType()) {
                    config.getTypeHandlerRegistry().register(mappedType, null, typeHandler);
                }
            }
        }
    }

}
